package per.hnvcam.util.console.cmd;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import per.hnvcam.util.console.ClientSupport;
import per.hnvcam.util.console.ConsoleInputStream;
import per.hnvcam.util.console.ConsoleOutputStream;

public class CMDClientSupport implements ClientSupport {
   private static final String CONSOLE = "cmd";

   private ConsoleInputStream inputStream;
   private ConsoleOutputStream outputStream;
   private ConsoleOutputStream errorStream;
   private Process process;
   private boolean isOpened;

   public CMDClientSupport() {
      inputStream = new ConsoleInputStream();
      outputStream = new ConsoleOutputStream();
      errorStream = new ConsoleOutputStream();
   }

   public void open() throws IOException {
      process = new ProcessBuilder(CONSOLE).start();
      isOpened = true;
      Thread output = new Thread(new SyncInputToOutput(process.getInputStream(), outputStream));
      output.setDaemon(true);
      output.start();
      Thread error = new Thread(new SyncInputToOutput(process.getErrorStream(), errorStream));
      error.setDaemon(true);
      error.start();
      Thread input = new Thread(new SyncInputToOutput(inputStream, process.getOutputStream()));
      input.setDaemon(true);
      input.start();
   }

   public boolean isOpened() {
      return isOpened;
   }

   public ConsoleOutputStream getOutputStream() {
      return outputStream;
   }

   public ConsoleInputStream getInputStream() {
      return inputStream;
   }

   public void close() {
      isOpened = false;
   }

   private class SyncInputToOutput implements Runnable {

      private InputStream input;
      private OutputStream output;

      public SyncInputToOutput(InputStream input, OutputStream output) {
         this.input = input;
         this.output = output;
      }

      public void run() {
         final byte[] buffer = new byte[4096];
         while (isOpened) {
            try {
               if (input.available() > 0) {
                  int length = input.read(buffer);
                  output.write(buffer, 0, length);
                  output.flush();
               }
               Thread.sleep(100);
            } catch (Exception e) {
               e.printStackTrace();
            }
         }
         try {
            input.close();
            output.close();
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
   }
   
   public Process getProcess() {
      return process;
   }

   public ConsoleOutputStream getErrorStream() {
      return errorStream;
   }
}
